package co.baiku.boot.shiro;

import co.baiku.boot.AjavaerCache;
import co.baiku.boot.cache.CaffeineShiroCache;
import co.baiku.boot.cache.RedisShiroCache;
import co.baiku.boot.cache.service.CacheService;
import co.baiku.boot.common.tools.StringTools;
import co.baiku.boot.config.ShiroConfig;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;

import java.util.concurrent.ConcurrentHashMap;

public class ShiroCacheManager implements CacheManager {

    private ShiroConfig shiroConfig;

    public void init(ShiroConfig shiroConfig) {
        this.shiroConfig = shiroConfig;
    }

    private ConcurrentHashMap cache = new ConcurrentHashMap();

    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
        if (StringTools.isBlank(name)) {
            return null;
        }
        Cache cache = (Cache) this.cache.get(name);
        if (cache == null) {
            if (shiroConfig.getCacheEngine() != null) {
                CacheService cacheHandle = AjavaerCache.engine(shiroConfig.getCacheEngine());
                if (cacheHandle != null) {
                    switch (shiroConfig.getCacheEngine()) {
                        case redis:
                            cache = new RedisShiroCache<>(shiroConfig);
                            break;
                        case caffeine:
                        default:
                            cache = new CaffeineShiroCache(cacheHandle);

                    }
                } else {
                    throw new CacheException("CacheEngine " + shiroConfig.getCacheEngine() + " has not been defined");
                }
            } else {
                cache = new CaffeineShiroCache(AjavaerCache.caffeine());
            }
            this.cache.put(name, cache);
        }

        return cache;
    }
}
